Skip to content

Preserve SHOTGUN_API_CACERTS precedence in shotgun_api3 cert patch#1122

Merged
stevelittlefish merged 2 commits into
masterfrom
ticket/SG-44256-shotgun-api-cacerts-precedence
Jul 20, 2026
Merged

Preserve SHOTGUN_API_CACERTS precedence in shotgun_api3 cert patch#1122
stevelittlefish merged 2 commits into
masterfrom
ticket/SG-44256-shotgun-api-cacerts-precedence

Conversation

@stevelittlefish

@stevelittlefish stevelittlefish commented Jul 17, 2026

Copy link
Copy Markdown
Contributor

Summary

  • _patch_shotgun_api3_certs() in tank_vendor/__init__.py currently returns the Core-extracted cacert.pem unconditionally whenever ca_certs isn't explicitly passed, silently bypassing the documented SHOTGUN_API_CACERTS environment variable.
  • On setups where the extracted cert lives on a slow network share, this made the first ShotGrid connection in a process pay a large one-time filesystem cost — reported by a studio as ~20-33s in Nuke 17.0 (vs <1s in Nuke 14.1), isolated experimentally to the cold read of the network-hosted cert path (see internal ticket SG-44256).
  • This restores shotgun_api3's own documented precedence: explicit ca_certs argument → SHOTGUN_API_CACERTS env var → extracted Core cert fallback.

Test plan

  • Added TestShotgunAPI3CertPatchPrecedence in tests/core_tests/test_tank_vendor.py, calling _patch_shotgun_api3_certs() directly against a throwaway fake pkgs.zip/certs/ layout so behavior can be verified without depending on the real build-time layout:
    • SHOTGUN_API_CACERTS set → wins over the extracted cert (the regression this fixes)
    • unset → unchanged fallback to the extracted cert
    • empty string → treated as unset
    • explicit ca_certs argument → still outranks everything, including the env var
  • Verified the new "wins over extracted cert" test fails against the pre-fix code and passes after the fix, confirming it actually exercises the bug rather than passing vacuously.
  • Full core_tests suite (510 tests) passes with the fix applied, no regressions.

Follow-up fix (review feedback)

CI/review caught that the new test's tearDown was leaking global state across test modules when the full suite ran in one process:

TypeError: _patched_get_certs_file() takes from 0 to 1 positional arguments but 2 were given

Root cause: setUp captured shotgun_api3.Shotgun._get_certs_file via plain attribute access, which unwraps the installed staticmethod descriptor down to a raw function. tearDown then reassigned that raw function directly as the class attribute, turning _get_certs_file back into a regular instance method. Any Shotgun(...) constructed by a later test in the same process (e.g. tests/util_tests/test_shotgun_connect.py) then called self._get_certs_file(ca_certs), which passed both self and ca_certs into a function that only accepts ca_certs.

Fix: snapshot the raw descriptor via shotgun_api3.Shotgun.__dict__["_get_certs_file"] instead of attribute access, so the staticmethod wrapper is preserved on restore.

  • Reproduced the failure by running core_tests.test_tank_vendor + util_tests.test_shotgun_connect in the same process (matches how the full suite runs).
  • Confirmed it's fixed: same two modules together now pass (35/35).
  • Full test suite (1253 tests) passes with no regressions.

_patch_shotgun_api3_certs() unconditionally returned the Core-extracted
cacert.pem whenever ca_certs wasn't explicitly passed, silently ignoring
the documented SHOTGUN_API_CACERTS environment variable. When the
extracted cert lives on a slow network share, this made every cold
ShotGrid connection pay a large one-time filesystem cost (~20-30s
observed in Nuke 17) that a local cert copy avoids.

Restore shotgun_api3's documented precedence: explicit ca_certs ->
SHOTGUN_API_CACERTS -> extracted Core cert fallback.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>

@carlos-villavicencio-adsk carlos-villavicencio-adsk left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM. Just one comment to be considered.

Comment thread python/tank_vendor/__init__.py
Comment thread python/tank_vendor/__init__.py

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This pull request restores shotgun_api3’s documented CA cert precedence in tank_vendor._patch_shotgun_api3_certs() so that SHOTGUN_API_CACERTS is honored when no explicit ca_certs argument is provided, avoiding unnecessary slow reads of the Core-extracted cert in some environments.

Changes:

  • Update the shotgun_api3 cert patch to respect SHOTGUN_API_CACERTS when ca_certs is not explicitly provided.
  • Add a new test suite validating precedence across: explicit ca_certs arg, env var (including empty string), and extracted cert fallback.

Reviewed changes

Copilot reviewed 2 out of 2 changed files in this pull request and generated 1 comment.

File Description
tests/core_tests/test_tank_vendor.py Adds a dedicated test class to validate cert precedence behavior for the shotgun_api3 cert patch.
python/tank_vendor/init.py Adjusts _patched_get_certs_file() to preserve SHOTGUN_API_CACERTS precedence before falling back to the extracted cert.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment thread tests/core_tests/test_tank_vendor.py Outdated
setUp() captured shotgun_api3.Shotgun._get_certs_file via attribute
access, which unwraps the staticmethod descriptor to a plain function.
Restoring that plain function in tearDown re-assigned it as a regular
instance method, so any Shotgun() constructed by a later test in the
same process passed both self and ca_certs into a function that only
accepts ca_certs, breaking unrelated tests (e.g.
util_tests/test_shotgun_connect.py) with:

  TypeError: _patched_get_certs_file() takes from 0 to 1 positional
  arguments but 2 were given

Snapshot the raw descriptor from Shotgun.__dict__ instead, so the
staticmethod wrapper is preserved on restore.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Comment thread tests/core_tests/test_tank_vendor.py
@codecov

codecov Bot commented Jul 17, 2026

Copy link
Copy Markdown

Codecov Report

✅ All modified and coverable lines are covered by tests.
✅ Project coverage is 80.10%. Comparing base (43a5ded) to head (2d5f90f).

Additional details and impacted files
@@           Coverage Diff           @@
##           master    #1122   +/-   ##
=======================================
  Coverage   80.10%   80.10%           
=======================================
  Files         203      203           
  Lines       19529    19529           
=======================================
  Hits        15643    15643           
  Misses       3886     3886           
Flag Coverage Δ
Linux 79.56% <ø> (ø)
Python-3.10 79.91% <ø> (+0.01%) ⬆️
Python-3.11 79.80% <ø> (-0.02%) ⬇️
Python-3.13 79.81% <ø> (+0.01%) ⬆️
Python-3.9 79.88% <ø> (+0.01%) ⬆️
Windows 79.56% <ø> (ø)
macOS 79.53% <ø> (ø)

Flags with carried forward coverage won't be shown. Click here to find out more.

☔ View full report in Codecov by Harness.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.

@stevelittlefish
stevelittlefish merged commit 2fd64cd into master Jul 20, 2026
28 checks passed
@stevelittlefish
stevelittlefish deleted the ticket/SG-44256-shotgun-api-cacerts-precedence branch July 20, 2026 10:18
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants